/**
 * @file app\tasks\mobus\devices\_mobus_command.c
 *
 * Copyright (C) 2023
 *
 * _mobus_command.c is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @author HinsShum hinsshum@qq.com
 *
 * @encoding utf-8
 */

/*---------- includes ----------*/
#include "protocol_mobus.h"
#include "relay.h"
#include "storage.h"

/*---------- macro ----------*/
#define relay_command_off 1
#define relay_command_on 2
#define relay_command_value 3
#define relay_command_negation 0x55
#define relay_command_negation 0x55

#define led_on 2
#define led_off 1
#define led_value 3
#define key_enable_command 4
#define key_disenable_command 5
#define key_all_disenable_command 7
#define key_all_enable_command 8
#define lianpai_mode     0x10

/*---------- type define ----------*/
/*---------- variable prototype ----------*/
/*---------- function prototype ----------*/
/*---------- variable ----------*/
static struct storage_key_struct* key = NULL;
static struct storage_led_struct* led = NULL;
uint8_t dev_channlx_sta_buffer[4] = { 0 };
/*---------- function ----------*/
static void _mobus_command(mobus_device_t self, uint8_t sub_channel,
    uint8_t* param, uint8_t length) {
    bool dly_flag = false;
    memset(dev_channlx_sta_buffer, 0, sizeof(dev_channlx_sta_buffer));
    assert(self);
    assert(param);
    assert(sub_channel < self->channel_nums);
    uint8_t command = param[0];
    uint8_t i = 0;
    xlog_message("Ruen INFO :Command data is: %02X \r\n", command);
    for (i = 0; i < length; i++)
        xlog_error("%02X ", param[i]);
    xlog_message("\r\n data length is %d\r\n", length);

    if (sub_channel == 0) {
        char key_num = 0;
        unsigned char led_value_t = 0;
        key = (struct storage_key_struct*)storage_get(STORAGE_AREA_KEY);
        led = (struct storage_led_struct*)storage_get(STORAGE_AREA_LIGHT_MODE);
        dev_channlx_sta_buffer[0] = 1;
        if (command == led_on) {
            if (led_assign_duty == 0)
            {
                led->led_mode = no_spuse;
                led->led_level = _led_value_max;
                led->assign_bright = 2.5 * _led_value_max;
                dev_channlx_sta_buffer[1] = _led_value_max;
            }
            else
            {
                led->led_mode = no_spuse;
                led->assign_bright = 2.5 * led_assign_duty;
                dev_channlx_sta_buffer[1] = led_assign_duty;
            }
            dly_flag = true;
        }
        else if (command == led_off) {
            led->assign_bright = 2.5 * _led_value_zero;
            led->led_mode = no_spuse;
            led->led_level = _led_value_zero;
            dev_channlx_sta_buffer[0] = 0;
            dev_channlx_sta_buffer[1] = _led_value_zero;
            dly_flag = true;
        }
        else if (command == led_value) {
            led_value_t = param[1];
            if (led_value_t == 0)
            {
                dev_channlx_sta_buffer[0] = 0;
            }
            else
            {
                led_assign_duty = led_value_t;
            }
            led->assign_bright = 2.5 * led_value_t;
            led->led_mode = no_spuse;
            dev_channlx_sta_buffer[1] = led_value_t;
            dly_flag = true;
        }
        else if (command == key_enable_command) {
            key_num = param[1] - 1;
            key->item[key_num].key_onoff = 1;
            key->dis_en_flag |= (1 << key_num);
            dly_flag = true;
            dev_channlx_sta_buffer[1] = led->assign_bright / 2.5;
        }
        else if (command == key_disenable_command) {
            key_num = param[1] - 1;
            key->item[key_num].key_onoff = 0;
            key->dis_en_flag &= ~(1 << key_num);
            dly_flag = true;
            dev_channlx_sta_buffer[1] = led->assign_bright / 2.5;

        }
        else if (command == key_all_disenable_command) {
            for (uint8_t i = 0; i < no_storage.temp_key.key_num; i++) {
                key->item[key_num].key_onoff = 0;
            }
            key->dis_en_flag = 0;
            dly_flag = true;
            dev_channlx_sta_buffer[1] = led->assign_bright / 2.5;

        }
        else if (command == key_all_enable_command) {
            for (uint8_t i = 0; i < no_storage.temp_key.key_num; i++) {
                key->item[key_num].key_onoff = 1;
            }
            key->dis_en_flag = 0xFFFF;
            dly_flag = true;
            dev_channlx_sta_buffer[1] = led->assign_bright / 2.5;
        }
        else if (command == lianpai_mode) {
            if (length < 10)
                return;
            no_storage.temp_lianpai.Temp_key_adress = param[1];
            no_storage.temp_lianpai.Temp_key_channl = param[7];
            no_storage.temp_lianpai.Temp_key_num = param[9];
            no_storage.temp_lianpai.Temp_local_mode = 2;
            no_storage.temp_lianpai.lianpai_Time = param[10];
            if (no_storage.temp_lianpai.lianpai_Time < 5 || no_storage.temp_lianpai.lianpai_Time > 10)
                no_storage.temp_lianpai.lianpai_Time = 5;
            no_storage.temp_lianpai.Temp_time_cnt = no_storage.temp_lianpai.lianpai_Time;
            dly_flag = true;
        }
        if (dly_flag == true) {
            storage_set(STORAGE_AREA_LIGHT_MODE, led, sizeof(struct storage_led_struct));
            storage_set(STORAGE_AREA_KEY, key, sizeof(struct storage_key_struct));
            dev_channlx_sta_buffer[2] = key->dis_en_flag & 0xFF;
            if (no_storage.temp_key.key_num <= 8)
                dev_channlx_sta_buffer[3] = 0;
            else
                dev_channlx_sta_buffer[3] = (key->dis_en_flag >> 8) & 0xFF;
            protocol_mobus_dev_report(MOBUS_FRAME_TYPE_UPLOAD_STATUS, sub_channel, dev_channlx_sta_buffer, 4);
            no_storage.led_temp_variable.dev_work_mode = LED_MODE_UPDATA;
        }
    }
    else if (sub_channel >= 1) {
        char relay_id = 0;
        relay_id = sub_channel - 1;
        if (length == 1) {
            if (command == relay_command_off) {
                open_relay_ornot_for_others(relay_id, false);
                no_storage.temp_relay.relay_out[relay_id] = 0;
            }
            else if (command == relay_command_on) {
                open_relay_ornot_for_others(relay_id, true);
                no_storage.temp_relay.relay_out[relay_id] = 1;
            }
            else if (command == relay_command_negation) {
                if (no_storage.temp_relay.relay_out[relay_id] == 0) {
                    open_relay_ornot_for_others(relay_id, true);
                    no_storage.temp_relay.relay_out[relay_id] = 1;
                }
                else if (no_storage.temp_relay.relay_out[relay_id] == 1) {
                    open_relay_ornot_for_others(relay_id, false);
                    no_storage.temp_relay.relay_out[relay_id] = 0;
                }
            }
        }
    }
}
static void _report_channlx_information(mobus_device_t self, uint8_t sub_channel) {
    memset(dev_channlx_sta_buffer, 0, sizeof(dev_channlx_sta_buffer));
    if (sub_channel == 0) {
        char key_num = 0;
        unsigned char led_value_t = 0;
        key = (struct storage_key_struct*)storage_get(STORAGE_AREA_KEY);
        led = (struct storage_led_struct*)storage_get(STORAGE_AREA_LIGHT_MODE);
        dev_channlx_sta_buffer[0] = 1;
        if (led->assign_bright == _led_value_zero) {
            dev_channlx_sta_buffer[0] = 0;
            dev_channlx_sta_buffer[1] = _led_value_zero;
        }
        else {
            dev_channlx_sta_buffer[0] = 0;
            dev_channlx_sta_buffer[1] = led->assign_bright / 2.5;
        }
        dev_channlx_sta_buffer[2] = key->dis_en_flag & 0xFF;
        if (no_storage.temp_key.key_num <= 8)
            dev_channlx_sta_buffer[3] = 0;
        else
            dev_channlx_sta_buffer[3] = (key->dis_en_flag >> 8) & 0xFF;
        protocol_mobus_dev_report(MOBUS_FRAME_TYPE_UPLOAD_STATUS, sub_channel, dev_channlx_sta_buffer, 4);
    }
    else if (sub_channel >= 1) {
    }

}